using System;
using System.IO;
using DecisionMaking.Domain;
using System.Collections.Generic;
using DecisionMaking.BusinessLogic.Model;
using Environment = DecisionMaking.Domain.Environment;

namespace DecisionMaking.BusinessLogic
{
	/// <summary>
	/// Responsible for Environment, Cue, CueAttribute, Candidate and Agent CRUD operations
	/// </summary>
	public interface IEnvironmentManager
	{
		/// <summary>
		/// Creates or updates the specified environment in persistent storage 
		/// </summary>
		/// <param name="model">
		/// A <see cref="EnvironmentModel"/>
		/// </param>
		/// <exception cref="DuplicateEnvironmentNameException">If an environment with the specified name already exists</exception>
		Environment SaveEnvironment(EnvironmentModel model);		
		
		/// <summary>
		/// Retrieves all environments created by the specified account 
		/// </summary>
		/// <param name="accountId">
		/// A <see cref="System.Int32"/>
		/// </param>
		/// <returns>
		/// A <see cref="IList<DecisionMaking.Domain.Environment>"/>
		/// </returns>
		IList<Environment> GetEnvironments(int accountId);

        /// <summary>
        /// Retrieves all environments created by the specified account or publicly visible environments
        /// </summary>
        /// <param name="accountId"></param>
        /// <returns></returns>
	    IList<Environment> GetPublicAndUsersEnvironments(int accountId);
				
		/// <summary>
		/// Returns the environment with the specified id or throws EntityNotFoundException if no such environment exists  
		/// </summary>
		/// <param name="environmentId">
		/// A <see cref="System.Int32"/>
		/// </param>
		/// <returns>
		/// A <see cref="DecisionMaking.Domain.Environment"/>
		/// </returns>
		Environment GetEnvironment(int environmentId);
				
		/// <summary>
		/// Gets all CueAttributes associated with the specified environment 
		/// </summary>
		/// <param name="environmentId">
		/// A <see cref="System.Int32"/>
		/// </param>
		/// <returns>
		/// A <see cref="IList<CueAttribute>"/>
		/// </returns>
		IList<CueAttribute> GetCueAttributes(int environmentId);

        /// <summary>
        /// Gets the cue attribute with the specified id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
	    CueAttribute GetCueAttribute(int id);
		
		/// <summary>
		/// Adds the specified CueAttribute to the specified Environment 
		/// </summary>
		/// <param name="environmentId">
		/// A <see cref="System.Int32"/>
		/// </param>
		/// <param name="model">
		/// A <see cref="CueAttributeModel"/>
		/// </param>
		/// <exception cref="DuplicateCueAttributeNameException">If two cue attributes have the same name</exception>
		CueAttribute AddCueAttribute(CueAttributeModel model);
		
		/// <summary>
		/// Deletes the specified CueAttribute 
		/// </summary>
		/// <param name="id">
		/// A <see cref="System.Int32"/>
		/// </param>
		void RemoveCueAttribute(int id);
		
		/// <summary>
		/// Return a list of Cues for the specified environment
		/// </summary>
		/// <param name="environmentId">
		/// A <see cref="System.Int32"/>
		/// </param>
		/// <returns>
		/// A <see cref="IList<Cue>"/>
		/// </returns>
		IList<Cue> GetCues(int environmentId);

        /// <summary>
        /// Returns the cue with the specified id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
	    Cue GetCue(int id);
		
		/// <summary>
		/// Adds the specified Cue to the specified Environment 
		/// </summary>
		/// <param name="model">
		/// A <see cref="CueModel"/>
		/// </param>
		/// <returns>
		/// A <see cref="Cue"/>
		/// </returns>
		/// <exception cref="DuplicateCueNameException">If two cues have the same name</exception>
		Cue SaveCue(CueModel model);	
		
		/// <summary>
		/// Deletes the specified Cue from its Environment 
		/// </summary>
		/// <param name="id">
		/// A <see cref="System.Int32"/>
		/// </param>
		void RemoveCue(int id);

        /// <summary>
        /// Returns the candidate with the specified id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
	    Candidate GetCandidate(int id);
        
        /// <summary>
        /// Returns a list of Candidates for the specified environment
        /// </summary>
        /// <param name="environmentId"></param>
        /// <returns>
        /// A <see cref="IList<Candidate>"/>
        /// </returns>
        IList<Candidate> GetCandidates(int environmentId);
		
		/// <summary>
		/// Creates or updates the specified candidate
		/// </summary>
		/// <param name="model"></param>
		/// <returns></returns>
        /// <exception cref="DuplicateCandidateNameException">If two candidate have the same name</exception>
		Candidate SaveCandidate(CandidateModel model);

        /// <summary>
        /// Deletes the specified Candidate from its Environment
        /// </summary>
        /// <param name="id"></param>
	    void RemoveCandidate(int id);

        /// <summary>
        /// Returns a list of Agents for the specified environment
        /// </summary>
        /// <param name="environmentId"></param>
        /// <returns></returns>
        IList<Agent> GetAgents(int environmentId);

		/// <summary>
		/// Deletes all existing agents, if any, and creates new agents with random CandidateCueValues 
		/// </summary>
		/// <param name="environmentId">
		/// A <see cref="System.Int32"/>
		/// </param>
		/// <param name="amount">
		/// A <see cref="System.Int32"/>
		/// </param>
		void GenerateAgents(int environmentId, int amount);

	    /// <summary>
	    /// Attempts to create an environment from an input CSV file
	    /// </summary>
	    /// <param name="accountId"></param>
	    /// <param name="csvInput"></param>
	    /// <returns></returns>
	    Environment ImportCsv(int accountId, Stream csvInput);
		
	}
}

